/*
 ------------------------------------------------------------------------------
 Copyright (C) 2006-2007 Team Blur.

 This file is part of the Quantum Engine source code.

 The Quantum Engine source code is free software; you can redistribute it and/or
 modify it under the terms of the GNU General Public License as published by
 the Free Software Foundation; either version 2 of the License, or (at your
 option) any later version.

 The Quantum Engine source code is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 more details.

 You should have received a copy of the GNU General Public License along with
 the Quantum Engine source code; if not, write to the Free Software Foundation, Inc.,
 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 ------------------------------------------------------------------------------
*/


#include "gamelib.h"


/*
 ==================
 odPlane::BoundsOnSide
 ==================
*/
int odPlane::BoundsOnSide (const odBounds &bounds) const {

	float	d1, d2;

	// Fast axial cases
	if (type < PLANETYPE_NONAXIAL){
		if (dist <= bounds[0][type])
			return PLANESIDE_FRONT;
		if (dist >= bounds[1][type])
			return PLANESIDE_BACK;

		return PLANESIDE_CROSS;
	}
	
	// General case
	switch (signBits){
	case 0:
		d1 = normal.x * bounds[1][0] + normal.y * bounds[1][1] + normal.z * bounds[1][2];
		d2 = normal.x * bounds[0][0] + normal.y * bounds[0][1] + normal.z * bounds[0][2];
		break;
	case 1:
		d1 = normal.x * bounds[0][0] + normal.y * bounds[1][1] + normal.z * bounds[1][2];
		d2 = normal.x * bounds[1][0] + normal.y * bounds[0][1] + normal.z * bounds[0][2];
		break;
	case 2:
		d1 = normal.x * bounds[1][0] + normal.y * bounds[0][1] + normal.z * bounds[1][2];
		d2 = normal.x * bounds[0][0] + normal.y * bounds[1][1] + normal.z * bounds[0][2];
		break;
	case 3:
		d1 = normal.x * bounds[0][0] + normal.y * bounds[0][1] + normal.z * bounds[1][2];
		d2 = normal.x * bounds[1][0] + normal.y * bounds[1][1] + normal.z * bounds[0][2];
		break;
	case 4:
		d1 = normal.x * bounds[1][0] + normal.y * bounds[1][1] + normal.z * bounds[0][2];
		d2 = normal.x * bounds[0][0] + normal.y * bounds[0][1] + normal.z * bounds[1][2];
		break;
	case 5:
		d1 = normal.x * bounds[0][0] + normal.y * bounds[1][1] + normal.z * bounds[0][2];
		d2 = normal.x * bounds[1][0] + normal.y * bounds[0][1] + normal.z * bounds[1][2];
		break;
	case 6:
		d1 = normal.x * bounds[1][0] + normal.y * bounds[0][1] + normal.z * bounds[0][2];
		d2 = normal.x * bounds[0][0] + normal.y * bounds[1][1] + normal.z * bounds[1][2];
		break;
	case 7:
		d1 = normal.x * bounds[0][0] + normal.y * bounds[0][1] + normal.z * bounds[0][2];
		d2 = normal.x * bounds[1][0] + normal.y * bounds[1][1] + normal.z * bounds[1][2];
		break;
	default:
		d1 = 0.0;
		d2 = 0.0;
		break;
	}

	if (d2 < dist){
		if (d1 >= dist)
			return PLANESIDE_CROSS;
		else
			return PLANESIDE_BACK;
	}

	return PLANESIDE_FRONT;
}

/*
 ==================
 odPlane::SphereOnSide
 ==================
*/
int odPlane::SphereOnSide (const odVec3 &center, float radius) const {

	float	d;

	if (type < PLANETYPE_NONAXIAL)
		d = center[type] - dist;
	else
		d = center.Dot(normal) - dist;

	if (d > radius)
		return PLANESIDE_FRONT;
	if (d < -radius)
		return PLANESIDE_BACK;

	return PLANESIDE_CROSS;
}

/*
 ==================
 odPlane::PointOnSide
 ==================
*/
int odPlane::PointOnSide (const odVec3 &point, float epsilon) const {

	float	d;

	if (type < PLANETYPE_NONAXIAL)
		d = point[type] - dist;
	else
		d = point.Dot(normal) - dist;

	if (d > epsilon)
		return PLANESIDE_FRONT;
	if (d < -epsilon)
		return PLANESIDE_BACK;

	return PLANESIDE_ON;
}

/*
 ==================
 odPlane::ToVec4
 ==================
*/
odVec4 odPlane::ToVec4 (void) const {

	return odVec4(normal.x, normal.y, normal.z, dist);
}

/*
 ==================
 odPlane::FromVec4
 ==================
*/
void odPlane::FromVec4 (const odVec4 &vec){

	normal.x = vec.x;
	normal.y = vec.y;
	normal.z = vec.z;
	dist = vec.w;
}

/*
 ==================
 odPlane::ToString

 This is just a convenience function for printing planes
 ==================
*/
const char *odPlane::ToString (int precision) const {

	return Str_FromFloatArray(ToFloatPtr(), 4, precision);
}
